package main;

import java.io.FileInputStream;
import java.io.FileReader;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import java_cup.runtime.Symbol;
import main.exceptions.CombinationsFileException;
import main.exceptions.CommandException;
import main.exceptions.ElementException;
import main.exceptions.ElementsFileException;
import model.Element;

public class Main {

	private static String elementsFile;
	private static String combinationsFile;
	private static Action action = Action.DEFAULT;

	private static Map<Integer, Element> elements = new HashMap<Integer, Element>();

	private enum Action {
		ELEMENT, TERMINALS, BASE, HELP, DEFAULT;
	};

	public static void main(String[] args) {
	
		Properties props = new Properties();
		try {
			props.load(new FileInputStream("config.properties"));
			elementsFile = props.getProperty("elementsFile");
			combinationsFile = props.getProperty("combinationsFile");
		} catch (Exception e) {
			System.out.println("Archivo de configuración inválido.");
			return;
		}
		
		if(args.length == 0) {
			try {
				launchGame();
			}catch(Exception e) {
				System.out.println("Comando inválido.");
			}
			return;
		}
		String action = args[0];
		try {
			if (action.equals("-e")) {
				setAction(Action.ELEMENT);
			}
			
			if (action.equals("-t")) {
				setAction(Action.TERMINALS);
			}
			
			if (action.equals("-b")) {
				setAction(Action.BASE);
			}
			
			if (action.equals("-h")) {
				setAction(Action.HELP);
			}
		}catch(Exception e) {
			System.out.println("Comando inválido. Para recibir ayuda ejecute con \"-h\"");
		}
		
		String arg = "";
		
		if(Main.action != Action.DEFAULT) {
			for(int i = 1; i < args.length; i++) {
				arg += " " + args[i];
			}
		}else{
			if(args.length > 0) {
				System.out.println("Comando inexistente. Para recibir ayuda ejecute con \"-h\"");
			}
		}
		
		for (int i = 0; i < args.length; i++) {

			if (args[i].equals("-n")) {
				elementsFile = args[++i];
			}

			if (args[i].equals("-m")) {
				combinationsFile = args[++i];
			}
			try {
				

			} catch (Exception e) {
				System.out.println("Comando inválido");
			}
		}

		try {
			launchGame();
		}catch(Exception e) {
			System.out.println("Elemento inválido");
		}
	}

	private static void setAction(Action action) throws CommandException {
		if (Main.action == Action.DEFAULT) {
			Main.action = action;
		} else {
			throw new CommandException();
		}
	}

	private static void launchGame() throws ElementException {
		if (action == Action.DEFAULT) {
			launchGame("");
		}
	}

	private static void launchGame(String arg) throws ElementException {
		try {
			Alchemy alchemy = new Alchemy(loadElements(elementsFile));
			switch (action) {
			case ELEMENT:
				alchemy.getAllCombinations(arg);
			case TERMINALS:
				alchemy.getTerminals();
				break;
			case BASE:
				alchemy.getOrigins(arg);
				break;
			case HELP:
				alchemy.help();
				break;
			default:
				alchemy.play();
			}

		} catch (ElementsFileException e) {
			System.out.println("Ruta de archivo de elementos inválida.");
		} catch (CombinationsFileException e) {
			System.out.println("Ruta de archivo de combinaciones inválida");
		}

	}

	private static Map<Integer, Element> loadElements(String filePath)
			throws ElementsFileException, CombinationsFileException {
		Symbol sym;
		NameLexer lexer;
		try {
			lexer = new NameLexer(new FileReader(filePath));

			int i = 1;
			while ((sym = lexer.next_token()).sym != 0) {
				elements.put(i++, new Element(sym.value.toString()));
			}

		} catch (Exception e) {
			e.printStackTrace();
			throw new ElementsFileException();
		}

		addCombinations();

		return elements;
	}

	private static void addCombinations() throws CombinationsFileException {
		MagicLexer lexer;
		try {
			lexer = new MagicLexer(new FileReader(combinationsFile));
			while (lexer.next_token().sym != 0) {
			}
		} catch (Exception e) {
			throw new CombinationsFileException();
		}
	}

	public static void makeCombination(String base1, String base2) {
		Element result;
		if (elements.containsValue(new Element(base1))
				&& elements.containsValue(new Element(base2))) {
			for (Element e : elements.values()) {
				if (e.getName().equals(base1)) {
					if ((result = e.combine(new Element(base2))) == null)
						System.out.println("????");
					else
						System.out.println(result);
				}
			}
		} else {
			System.out.println("????");
		}
	}

	public static void addCombination(int elementId, int base1, int base2)
			throws ElementException {
		try {
			elements.get(base1).addCombination(elements.get(base2),
					elements.get(elementId));
			elements.get(base2).addCombination(elements.get(base1),
					elements.get(elementId));
			elements.get(elementId).addOrigin(elements.get(base1));
			elements.get(elementId).addOrigin(elements.get(base2));
		} catch (Exception e) {
			throw new ElementException("Inexistent element.");
		}
	}

	public static void addElement(String name) {
		elements.put(elements.keySet().size() + 1, new Element(name));
	}

}
